package cn.ftp;

import java.io.File;
import java.io.IOException;
import java.net.Socket;

public class FTPClient {
	
	private Socket controlSocket = null;
	private Socket dataSocket = null;
	
	
	public FTPClient() {
		try {
			controlSocket = new Socket(MyUtil.defaultIp, MyUtil.defaultPort);
			ClientHandler clientHandler = new ClientHandler(controlSocket);
			Thread handlerThread = new Thread(clientHandler);
			handlerThread.start();
		} catch (IOException e) {
			System.out.println("Client error: " + e);
		}
	}
}
class ClientHandler extends FTPHandler implements Runnable {
	
	private Socket socket = null;
	
	public ClientHandler(Socket socket) {
		super(socket);
		if (socket != null) {
			this.socket = socket;
		}
	}
	
	public static enum State {
		Connected, User, Pass, Type, Epsv, 
		Operate, Trans, End
	};
	
	private State state = State.Connected;
	private Socket transSocket = null;
	boolean isSend = false;
	String homeDir = "D:/FTP/client/";
	String path = null;
	boolean isExit = false;
	public void run() {
		MyUtil.Command command = null;
		int newport = 0;
		
		while (true) {
			if (isExit) {
				break;
			}
			
			String line = super.readLine();
			
			
			if (line.contains("|||")) {
				String p = line.substring(line.indexOf("|||") + 3, line.indexOf("|)"));
				newport = Integer.parseInt(p);
				super.buildTransSocket(newport);
			}
			
			if (line == null || line.length() == 0) {
				break;
			}
			int code = MyUtil.getCode(line);
			
			if (code == 150) {
				if (isSend) {
					super.setPath(path, isSend);
				} else {
					super.setPath(homeDir, isSend);
				}
			}
			if (code == 257) {
				System.out.println(MyUtil.getContent(line));
			}
//			System.out.println(state);
			switch (state) {
			case Connected:
				if (code == 220) {
					state = State.User;
					super.writeLine("USER WangYan");
				}
				break;
			case User:
				if (code == 331) {
					state = State.Pass;
					super.writeLine("PASS 2010011316");
				}
				break;
			case Pass:
				if (code == 230) {
					state = State.Type;
					super.writeLine("TYPE I");
				}
				break;
			case Type:
//				if (code == 200) {
					state = State.Operate;
					super.writeLine("PASV");
//				}
				break;
			case Epsv:
//				if (code == 200) {
					state = State.Operate;
					super.writeLine("EPSV");
//				}
				break;
			case Operate:
				line = MyUtil.getInputLine(null);
				dealOperate(line);
				break;
			case Trans:
				break;
			case End:
				break;
			default:
				super.writeLine("PWD");
				break;
			}			
			
		}
//		System.out.println("The ClientHandler is done");
//		super.close();
	}
	
	private void dealOperate(String line) {
//		super.writeLine(line);
		if (line == null) return;
		try {
			MyUtil.Command command = MyUtil.getCommand(line.trim());
			switch (command) {
			case RETR:
				this.isSend = false;
				super.writeLine(command.toString() + MyUtil.SP +
						MyUtil.getContent(line));
				this.state = State.Type;
				break;
			case STOR:
				this.isSend = true;
//				System.out.println(this.isSend);
				super.writeLine(command.toString() + MyUtil.SP +
						MyUtil.getContent(line));
				path = homeDir + MyUtil.getContent(line);
				this.state = State.Type;
				break;
			case CWD:
				isSend = false;
				super.writeLine(command.toString() + MyUtil.SP +
						MyUtil.getContent(line));
				break;
			case LIST:
				isSend = false;
				super.writeLine(command.toString());
				super.setPath(homeDir, false);
				this.state = State.Type;
				break;
			case PWD:
				super.writeLine(command.toString());
				
				break;
			case HELP:
				super.writeLine(command.toString());
				this.state = State.Type;
				break;
			case QUIT:
				isSend = false;
				super.writeLine(command.toString());
				isExit = true;
				break;
			default:
				System.out.println("Unrecognized command");
				super.writeLine("PWD");
				break;
			}
			if (isExit) {
				super.close();
				System.exit(0);
			}
		} catch (Exception e) {
			super.writeLine(line);
		}
	}
	
}

